import os
import shutil

from django.core.exceptions import ObjectDoesNotExist
from django.core.files.storage import default_storage
from django.db import transaction
from rest_framework.parsers import MultiPartParser, JSONParser, FormParser
from rest_framework.views import APIView
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi

from application import settings
from .models import Project
from .serializers import ProjectSerializer, CreateProjectSerializer, UpdateProjectSerializer, DetailProjectSerializer, \
    ListProjectSerializer
from ..AssetsManagement.models import Asset
from ..CanvasesManagement.models import Canvas
from ..HistoryManagement.models import ProjectHistory
from ..utils.response_utils import api_response, ResponseCode

DEFAULT_THUMBNAIL_PATH = 'images/default.png'


def safe_delete_file(path):
    if path and path != DEFAULT_THUMBNAIL_PATH:
        if default_storage.exists(path):
            default_storage.delete(path)


class ListProjectsView(APIView):
    """
    项目列表接口
    """

    @swagger_auto_schema(
        operation_description="获取项目列表",
        responses={
            200: ListProjectSerializer,
            500: openapi.Response(
                description="服务器错误",
            )
        },
        tags=["项目管理"]
    )
    def get(self, request):
        try:
            queryset = Project.objects.all().order_by('-created_at')
            serializer = ListProjectSerializer(queryset, many=True)
            return api_response(ResponseCode.SUCCESS, "获取成功", serializer.data)
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, str(e))


class CreateProjectView(APIView):
    """
    创建新项目接口
    """

    @swagger_auto_schema(
        operation_description="创建新项目",
        request_body=CreateProjectSerializer,
        responses={
            200: ProjectSerializer,
            400: openapi.Response(
                description="参数错误",
            )
        },
        tags=["项目管理"]
    )
    def post(self, request):
        try:
            serializer = CreateProjectSerializer(data=request.data)
            if serializer.is_valid():
                project = serializer.save()
                fall_serializer = ProjectSerializer(project)
                return api_response(ResponseCode.SUCCESS, "项目创建成功", fall_serializer.data)
            return api_response(ResponseCode.BAD_REQUEST, f"参数错误：{serializer.errors}")
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, f"服务器错误: {str(e)}")


class ProjectDetailView(APIView):
    """
    项目详情接口（自动同步最新历史版本）
    """

    @swagger_auto_schema(
        operation_description="获取项目详情（自动同步最新历史版本）",
        manual_parameters=[
            openapi.Parameter('project_id', openapi.IN_PATH, type=openapi.TYPE_STRING)
        ],
        responses={
            200: DetailProjectSerializer,
            404: openapi.Response(description="项目不存在"),
            500: openapi.Response(description="服务器错误")
        },
        tags=["项目管理"]
    )
    def get(self, request, project_id):
        try:
            # 获取项目及最新历史记录
            project = Project.objects.get(id=project_id)
            latest_history = ProjectHistory.objects.filter(project=project).order_by('-created_at').first()

            # 存在有效历史记录时进行版本对比
            if latest_history:
                # 时区处理确保时间类型一致
                project_time = project.last_modified or project.updated_at
                history_time = latest_history.created_at

                # 当历史版本较新时执行数据恢复
                if history_time > project_time:
                    self._restore_from_history(project, latest_history)
                    project.refresh_from_db()  # 刷新项目实例

            # 序列化最终数据
            serializer = DetailProjectSerializer(project)
            return api_response(ResponseCode.SUCCESS, "获取成功", serializer.data)

        except ObjectDoesNotExist:
            return api_response(ResponseCode.NOT_FOUND, "项目不存在")
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, str(e))

    def _restore_from_history(self, project, history):
        """从历史记录恢复项目状态"""
        from ..CanvasesManagement.models import Canvas
        from ..CanvasElementManagement.models import CanvasElement

        try:
            # 原子操作保证数据一致性
            with transaction.atomic():
                # 恢复项目基础信息
                project.name = history.project_snapshot.get('name', project.name)
                project.description = history.project_snapshot.get('description', project.description)
                project.settings = history.project_snapshot.get('settings', project.settings)
                project.thumbnail_url = history.project_snapshot.get('thumbnail_url', project.thumbnail_url)
                project.last_modified = history.created_at  # 更新最后修改时间为历史记录时间
                project.save()

                # 删除现有画布及元素（级联删除）
                Canvas.objects.filter(project=project).delete()

                # 重建画布结构
                for canvas_data in history.canvas_snapshot:
                    # 创建画布
                    canvas = Canvas.objects.create(
                        id=canvas_data['id'],
                        project=project,
                        name=canvas_data['name'],
                        position=canvas_data.get('position', 0),
                        canvas_size=canvas_data.get('canvas_size', {'width': 1920, 'height': 1080}),
                        background=canvas_data.get('background', {}),
                        background_image=canvas_data.get('background_image', ''),
                        original_size=canvas_data.get('original_size', {'width': 1920, 'height': 1080})
                    )

                    # 关联元素恢复
                    element_mapping = {}  # 用于处理元素间关联关系
                    for element_data in history.element_snapshot:
                        if element_data['canvas'] == canvas_data['id']:
                            # 创建画布元素
                            element = CanvasElement.objects.create(
                                id=element_data['id'],
                                canvas=canvas,
                                type=element_data['type'],
                                name=element_data.get('name', ''),
                                position=element_data.get('position', {'x': 0, 'y': 0}),
                                size=element_data.get('size', {'width': 0, 'height': 0}),
                                rotation=element_data.get('rotation', 0),
                                opacity=element_data.get('opacity', 1),
                                visible=element_data.get('visible', True),
                                locked=element_data.get('locked', False),
                                z_index=element_data.get('z_index', 0)
                            )
                            element_mapping[element_data['id']] = element

                            # 处理元素类型特定数据
                            if element_data['type'] == 'mask' and element_data.get('mask_element'):
                                self._restore_mask_element(element, element_data['mask_element'])
                            elif element_data['type'] == 'text' and element_data.get('text_element'):
                                self._restore_text_element(element, element_data['text_element'])

                # 更新项目最后修改时间
                project.last_modified = history.created_at
                project.save()

        except Exception as e:
            raise Exception(f"历史记录恢复失败: {str(e)}")

    def _restore_mask_element(self, element, mask_data):
        from ..CanvasElementManagement.models import MaskElement
        MaskElement.objects.create(
            element=element,
            mask_type=mask_data.get('mask_type', 'image'),
            mask_content=mask_data.get('mask_content', {}),
            asset_id=mask_data.get('asset', {}).get('id')  # 处理关联资产
        )

    def _restore_text_element(self, element, text_data):
        from ..CanvasElementManagement.models import TextElement
        TextElement.objects.create(
            element=element,
            text_content=text_data.get('text_content', ''),
            font_family=text_data.get('font_family', 'Arial'),
            font_size=text_data.get('font_size', 12),
            font_weight=text_data.get('font_weight', 'normal'),
            font_style=text_data.get('font_style', 'normal'),
            text_align=text_data.get('text_align', 'left'),
            line_height=text_data.get('line_height', 1.2),
            letter_spacing=text_data.get('letter_spacing', 0),
            text_color=text_data.get('text_color', '#000000'),
            text_effects=text_data.get('text_effects', {}),
            text_transform=text_data.get('text_transform', 'none'),
            writing_mode=text_data.get('writing_mode', 'horizontal-tb')
        )


class UpdateProjectView(APIView):
    """
    更新项目接口
    """
    parser_classes = [JSONParser]

    @swagger_auto_schema(
        operation_description="更新项目信息（Base64缩略图）",
        request_body=UpdateProjectSerializer,
        responses={
            200: UpdateProjectSerializer,
            400: "参数错误",
            404: "项目不存在"
        },
        tags=["项目管理"]
    )
    def put(self, request, project_id):
        try:
            project = Project.objects.get(id=project_id)
            serializer = UpdateProjectSerializer(project, data=request.data, context={'project': project}, partial=True)

            if serializer.is_valid():
                serializer.save()
                return api_response(ResponseCode.SUCCESS, "更新成功", serializer.data)
            return api_response(ResponseCode.BAD_REQUEST, serializer.errors)

        except ObjectDoesNotExist:
            return api_response(ResponseCode.NOT_FOUND, "项目不存在")
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, f"服务器错误: {str(e)}")


class DeleteProjectView(APIView):
    """
    删除项目接口
    """

    @swagger_auto_schema(
        operation_description="删除项目",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=['project_ids'],
            properties={
                'project_ids': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_STRING),
                                              description="项目ID列表"),
            }
        ),
        responses={
            200: openapi.Response(
                description="删除成功",
            ),
            404: openapi.Response(
                description="项目不存在",
            )
        },
        tags=["项目管理"]
    )
    def delete(self, request):
        project_ids = request.data.get('project_ids', [])
        if not project_ids and not isinstance(project_ids, list):
            return api_response(ResponseCode.BAD_REQUEST, "参数错误")
        not_found_ids = []
        for project_id in project_ids:
            try:
                project = Project.objects.get(id=project_id)
                # 删除缩略图文件
                if project.thumbnail_url and project.thumbnail_url != DEFAULT_THUMBNAIL_PATH:
                    if default_storage.exists(project.thumbnail_url):
                        default_storage.delete(project.thumbnail_url)

                thumbnail_root = os.path.join(settings.MEDIA_ROOT, 'images', str(project.name))
                canvas_bg_root = os.path.join(settings.MEDIA_ROOT, 'canvas_bg', str(project.name))
                if os.path.exists(thumbnail_root):
                    shutil.rmtree(thumbnail_root, ignore_errors=True)
                if os.path.exists(canvas_bg_root):
                    shutil.rmtree(canvas_bg_root, ignore_errors=True)

                # 处理画布文件
                for canvas in Canvas.objects.filter(project=project):
                    safe_delete_file(canvas.background_image)

                # 处理资源文件
                for asset in Asset.objects.filter(project=project):
                    safe_delete_file(asset.url)

                project.delete()
            except ObjectDoesNotExist:
                not_found_ids.append(project_id)
        if not_found_ids:
            return api_response(ResponseCode.NOT_FOUND,
                                f"成功删除项目: {len(project_ids) - len(not_found_ids)}个，未找到项目ID: {', '.join(not_found_ids)}")
        return api_response(ResponseCode.SUCCESS, "删除成功")
